#include "db_schema.h"
#include "logger.h"
#include <stdlib.h>
#include <string.h>

int db_schema_init(sqlite3 *db) {
    if (!db) {
        return ERROR_INVALID_PARAM;
    }

    int rc = db_schema_create_tables(db);
    if (rc != SUCCESS) {
        return rc;
    }

    rc = db_schema_create_indexes(db);
    if (rc != SUCCESS) {
        return rc;
    }

    return SUCCESS;
}

int db_schema_create_tables(sqlite3 *db) {
    const char *create_tables_sql[] = {
        // 配置表
        "CREATE TABLE IF NOT EXISTS config ("
        "    key TEXT PRIMARY KEY,"
        "    value TEXT NOT NULL,"
        "    type TEXT NOT NULL DEFAULT 'string',"
        "    description TEXT,"
        "    created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
        "    updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))"
        ");",

        // 数据池表
        "CREATE TABLE IF NOT EXISTS datapool ("
        "    key TEXT PRIMARY KEY,"
        "    value TEXT NOT NULL,"
        "    timestamp INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
        "    created_at INTEGER NOT NULL DEFAULT (strftime('%s','now')),"
        "    updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))"
        ");",

        // 事件日志表
        "CREATE TABLE IF NOT EXISTS event_log ("
        "    id INTEGER PRIMARY KEY AUTOINCREMENT,"
        "    type INTEGER NOT NULL,"
        "    source TEXT NOT NULL,"
        "    description TEXT NOT NULL,"
        "    data TEXT,"
        "    created_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))"
        ");",

        // 系统状态表
        "CREATE TABLE IF NOT EXISTS system_status ("
        "    component TEXT PRIMARY KEY,"
        "    status TEXT NOT NULL,"
        "    details TEXT,"
        "    updated_at INTEGER NOT NULL DEFAULT (strftime('%s','now'))"
        ");",

        NULL
    };

    char *err_msg = NULL;
    for (int i = 0; create_tables_sql[i] != NULL; i++) {
        int rc = sqlite3_exec(db, create_tables_sql[i], NULL, NULL, &err_msg);
        if (rc != SQLITE_OK) {
            LOG_ERROR("Failed to create table: %s", err_msg);
            sqlite3_free(err_msg);
            return ERROR_DB_OPERATION;
        }
    }

    return SUCCESS;
}

int db_schema_create_indexes(sqlite3 *db) {
    const char *create_indexes_sql[] = {
        "CREATE INDEX IF NOT EXISTS idx_event_log_type ON event_log(type);",
        "CREATE INDEX IF NOT EXISTS idx_event_log_created_at ON event_log(created_at);",
        "CREATE INDEX IF NOT EXISTS idx_event_log_source ON event_log(source);",
        "CREATE INDEX IF NOT EXISTS idx_datapool_timestamp ON datapool(timestamp);",
        "CREATE INDEX IF NOT EXISTS idx_system_status_updated_at ON system_status(updated_at);",
        NULL
    };

    char *err_msg = NULL;
    for (int i = 0; create_indexes_sql[i] != NULL; i++) {
        int rc = sqlite3_exec(db, create_indexes_sql[i], NULL, NULL, &err_msg);
        if (rc != SQLITE_OK) {
            LOG_ERROR("Failed to create index: %s", err_msg);
            sqlite3_free(err_msg);
            return ERROR_DB_OPERATION;
        }
    }

    return SUCCESS;
}

db_config_item_t *db_config_item_create(const char *key, const char *value,
                                        const char *type, const char *description) {
    db_config_item_t *item = malloc(sizeof(db_config_item_t));
    if (!item) {
        return NULL;
    }

    item->key = key ? strdup(key) : NULL;
    item->value = value ? strdup(value) : NULL;
    item->type = type ? strdup(type) : NULL;
    item->description = description ? strdup(description) : NULL;
    item->created_at = time(NULL);
    item->updated_at = time(NULL);

    return item;
}

void db_config_item_free(db_config_item_t *item) {
    if (item) {
        if (item->key) free(item->key);
        if (item->value) free(item->value);
        if (item->type) free(item->type);
        if (item->description) free(item->description);
        free(item);
    }
}

db_datapool_item_t *db_datapool_item_create(const char *key, json_t *value) {
    db_datapool_item_t *item = malloc(sizeof(db_datapool_item_t));
    if (!item) {
        return NULL;
    }

    item->key = key ? strdup(key) : NULL;
    item->value = value ? json_incref(value) : NULL;
    item->timestamp = time(NULL);
    item->created_at = time(NULL);
    item->updated_at = time(NULL);

    return item;
}

void db_datapool_item_free(db_datapool_item_t *item) {
    if (item) {
        if (item->key) free(item->key);
        if (item->value) json_decref(item->value);
        free(item);
    }
}
